<?php

namespace App\Models\Trip\History\Repositories;

use App\Models\Common\Area\Repositories\Interfaces\AreaRepositoryInterface;
use App\Models\Plane\Airports\Repositories\Interfaces\AirportRepositoryInterface;
use App\Models\Plane\Cities\Repositories\Interfaces\PlaneCityRepositoryInterface;
use App\Models\Train\Stations\Repositories\Interfaces\StationRepositoryInterface;
use App\Models\Trip\History\TripQueryHistory;
use App\Trip\Orders\TripType;
use App\Trip\Repository\BaseRepository;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Collection;

class TripQueryHistoryRepository extends BaseRepository implements Interfaces\TripQueryHistoryRepositoryInterface
{

    public function __construct(TripQueryHistory $model)
    {
        parent::__construct($model);
    }

    /**
     * @param string $user_id
     * @param array  $data
     * @return TripQueryHistory
     * @throws Exception
     */
    public function addByUserId(string $user_id, array $data): TripQueryHistory
    {
        $recode = $this->findOneByUserCode($user_id, $data['from_code'], $data['to_code'], $data['trip_type']);
        if ($recode) {
            // 更新时间~~
            $updated_at = $data['updated_at'] ?? '';
            $recode->update([
                'updated_at' => $updated_at ?: Carbon::now()->toDateTimeString(),
            ]);
            return $recode;
        }

        if ($data['trip_type'] == TripType::TRIP_TYPE_TRAIN) {
            $hisData = $this->buildTrainData($data);
        } elseif ($data['trip_type'] == TripType::TRIP_TYPE_PLANE) {
            $hisData = $this->buildPlaneData($data);
        } else {
            throw new Exception("暂不支持的类型");
        }
        $hisData['user_id'] = $user_id;
        return $this->create($hisData);
    }

    /**
     * @param string $user_id
     * @param string $from_code
     * @param string $to_code
     * @param int    $trip_type
     * @return TripQueryHistory|null
     */
    public function findOneByUserCode(string $user_id, string $from_code, string $to_code, int $trip_type = 0): ?TripQueryHistory
    {
        $where = [
            'user_id'   => $user_id,
            'from_code' => $from_code,
            'to_code'   => $to_code,
        ];
        if ($trip_type > 0) {
            $where['trip_type'] = $trip_type;
        }
        return $this->findOneBy($where);
    }

    private function buildTrainData($data): array
    {
        $from_name    = "";
        $from_name_uy = "";
        $to_name      = "";
        $to_name_uy   = "";
        $areaRepo     = app(AreaRepositoryInterface::class);
        $stationRepo  = app(StationRepositoryInterface::class);
        switch ($data['from_type']) {
            case 0: // 城市
            case 1:  // 区域
                $from         = $areaRepo->findByCode($data['from_code']);
                $from_name    = $from?->getAreaName() ?: '';
                $from_name_uy = $from?->getAreaNameUy() ?: '';
                break;
            case 2: // 站点
                $from         = $stationRepo->findOneByCode($data['from_code']);
                $from_name    = $from?->getStationName() ?: '';
                $from_name_uy = $from?->getStationNameUy() ?: '';
                break;
        }


        switch ($data['to_type']) {
            case 0: // 城市
            case 1:// 区域
                $to         = $areaRepo->findByCode($data['to_code']);
                $to_name    = $to?->getAreaName() ?: '';
                $to_name_uy = $to?->getAreaNameUy() ?: '';
                break;
            case 2:
                $to         = $stationRepo->findOneByCode($data['to_code']);
                $to_name    = $to?->getStationName() ?: '';
                $to_name_uy = $to?->getStationNameUy() ?: '';
                break;
        }
        return [

            'trip_type'    => $data['trip_type'],
            'from_type'    => $data['from_type'],
            'to_type'      => $data['to_type'],
            'from_code'    => $data['from_code'],
            'to_code'      => $data['to_code'],
            'from_name'    => $from_name,
            'from_name_uy' => $from_name_uy,
            'to_name'      => $to_name,
            'to_name_uy'   => $to_name_uy,
        ];
    }

    private function buildPlaneData($data): array
    {
        $from_name    = "";
        $from_name_uy = "";
        $to_name      = "";
        $to_name_uy   = "";

        $airportRepo     = app(AirportRepositoryInterface::class);
        $airportCityRepo = app(PlaneCityRepositoryInterface::class);
        $areaRepo        = app(AreaRepositoryInterface::class);
        switch ($data['from_type']) {
            case 0: // 城市三字码
                if (is_numeric($data['from_code'])) {
                    // 区域码
                    $city = $airportCityRepo->findOneByAdCode($data['from_code']);
                } else {
                    // 三字码
                    $city = $airportCityRepo->findOneByCode($data['from_code']);
                }
                $city_area    = $city?->adcode ? $areaRepo->findByCode($city->adcode) : null;
                $from_name    = $city_area?->getAreaName() ?: '';
                $from_name_uy = $city_area?->getAreaNameUy() ?: '';
                break;
            case 2: // 站点
                $from         = $airportRepo->findOneByCode($data['from_code']);
                $from_name    = $from?->getShortName() ?: '';
                $from_name_uy = $from?->getShortNameUy() ?: '';
                break;
        }


        switch ($data['to_type']) {
            case 0:
                if (is_numeric($data['to_code'])) {
                    // 区域码
                    $city2 = $airportCityRepo->findOneByAdCode($data['to_code']);
                } else {
                    // 三字码
                    $city2 = $airportCityRepo->findOneByCode($data['to_code']);
                }
                $city_area2 = $city2->adcode ? $areaRepo->findByCode($city2->adcode) : null;
                $to_name    = $city_area2?->getAreaName() ?: '';
                $to_name_uy = $city_area2?->getAreaNameUy() ?: '';
                break;
            case 2:
                $to         = $airportRepo->findOneByCode($data['to_code']);
                $to_name    = $to?->getShortName() ?: '';
                $to_name_uy = $to?->getShortNameUy() ?: '';
                break;
        }
        return [
            'trip_type'    => $data['trip_type'],
            'from_type'    => $data['from_type'],
            'to_type'      => $data['to_type'],
            'from_code'    => $data['from_code'],
            'to_code'      => $data['to_code'],
            'from_name'    => $from_name,
            'from_name_uy' => $from_name_uy,
            'to_name'      => $to_name,
            'to_name_uy'   => $to_name_uy,
        ];
    }

    /**
     * @param string    $user_id
     * @param int|array $trip_type
     * @param int       $limit
     * @return Collection
     */
    public function listByUserId(string $user_id, array|int $trip_type, int $limit = 6): Collection
    {
        return $this->model->where('user_id', $user_id)
                           ->when($trip_type, function ($query) use ($trip_type) {
                               if (is_array($trip_type)) {
                                   $query->whereIn('trip_type', $trip_type);
                               } else {
                                   $query->where('trip_type', $trip_type);
                               }
                           })
                           ->orderByDesc('updated_at')
                           ->limit($limit)
                           ->get();
    }

    /**
     * @param string    $user_id
     * @param int|array $trip_type
     * @return bool
     */
    public function clearByUserId(string $user_id, array|int $trip_type): bool
    {
        return $this->model->where('user_id', $user_id)
                           ->when($trip_type, function ($query) use ($trip_type) {
                               if (is_array($trip_type)) {
                                   $query->whereIn('trip_type', $trip_type);
                               } else {
                                   $query->where('trip_type', $trip_type);
                               }
                           })
                           ->delete();
    }
}